package com.xzq.erp.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xzq.erp.domain.dto.PageDTO;
import com.xzq.erp.domain.dto.RoleDTO;
import com.xzq.erp.domain.dto.RolePermissionDTO;
import com.xzq.erp.domain.po.SysPermission;
import com.xzq.erp.domain.po.SysRole;
import com.xzq.erp.domain.po.SysRoleMenu;
import com.xzq.erp.domain.po.SysRolePermission;
import com.xzq.erp.domain.query.RolePageQuery;
import com.xzq.erp.domain.vo.RoleVO;
import com.xzq.erp.enums.ResponseCodeEnum;
import com.xzq.erp.exception.BizException;
import com.xzq.erp.mapper.SysRoleMapper;
import com.xzq.erp.mapper.SysRolePermissionMapper;
import com.xzq.erp.service.ISysPermissionService;
import com.xzq.erp.service.ISysRoleMenuService;
import com.xzq.erp.service.ISysRolePermissionService;
import com.xzq.erp.service.ISysRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统角色表 服务实现类
 * </p>
 *
 * @author xzq
 * @since 2025-05-19
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    private final SysRolePermissionMapper sysRolePermissionMapper;

    private final ISysPermissionService sysPermissionService;

    private final ISysRoleMenuService sysRoleMenuService;

    @Override
    public PageDTO<RoleVO> getRoleList(RolePageQuery query) {
        PageHelper.startPage(query.getCurrent(), query.getSize());
        List<SysRole> list = lambdaQuery()
                .like(StrUtil.isNotBlank(query.getName()), SysRole::getLabel, query.getName())
                .eq(Objects.nonNull(query.getStatus()), SysRole::getStatus, query.getStatus())
                .orderByDesc(SysRole::getCreateTime)
                .list();
        PageInfo<SysRole> page = new PageInfo<>(list);
        List<SysRole> records = page.getList();
        if(CollectionUtils.isEmpty(records)){
            return PageDTO.empty(page.getTotal(), (long)page.getPages());
        }
        List<RoleVO> roleVOS = new ArrayList<>(records.size());
        for(SysRole record : records){
            RoleVO roleVO = new RoleVO()
                    .setId(record.getId())
                    .setName(record.getLabel())
                    .setRoleKey(record.getName())
                    .setStatus(record.getStatus())
                    .setRemark(record.getRemark())
                    .setCreateTime(record.getCreateTime());
            roleVOS.add(roleVO);
        }
        return PageDTO.of(new Page<>(page.getTotal(), (long)page.getPages()), roleVOS);
    }

    @Override
    public List<Integer> getRolePermissions(Integer roleId) {
        List<SysRolePermission> list = sysRolePermissionMapper.selectList(new LambdaQueryWrapper<SysRolePermission>()
                .eq(SysRolePermission::getRoleId, roleId)
                .gt(SysRolePermission::getPermissionId, 10000));
        return list.stream().map(SysRolePermission::getPermissionId).collect(Collectors.toList());
    }

    @Override
    public List<String> getRoleIdsPermissions(List<Integer> roleIds) {
        List<String> permissions = new ArrayList<>();
        List<SysRolePermission> list = sysRolePermissionMapper.selectList(new LambdaQueryWrapper<SysRolePermission>()
                .in(SysRolePermission::getRoleId, roleIds)
                .gt(SysRolePermission::getPermissionId, 10000)
        );
        if(CollectionUtils.isEmpty(list)){
            return permissions;
        }
        List<SysPermission> sysPermissionList = sysPermissionService.lambdaQuery()
                .in(SysPermission::getId, list.stream().map(SysRolePermission::getPermissionId).collect(Collectors.toList()))
                .list();
        if(CollectionUtils.isEmpty(sysPermissionList)){
            return permissions;
        }
        for(SysPermission sysPermission : sysPermissionList){
            permissions.add(sysPermission.getName());
        }
        return permissions;
    }

    @Override
    public void addRole(RoleDTO roleDTO) {
        SysRole sysRole = new SysRole()
                .setName(roleDTO.getRoleKey())
                .setLabel(roleDTO.getName())
                .setStatus(roleDTO.getStatus())
                .setRemark(roleDTO.getRemark());
        save(sysRole);
    }

    @Override
    public void updateRole(RoleDTO roleDTO) {
        if(Objects.isNull(roleDTO.getId())){
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);
        }
        SysRole sysRole = new SysRole()
                .setId(roleDTO.getId())
                .setName(roleDTO.getRoleKey())
                .setLabel(roleDTO.getName())
                .setStatus(roleDTO.getStatus())
                .setRemark(roleDTO.getRemark());
        updateById(sysRole);
    }

    @Override
    public void updateRoleStatus(Integer roleId, Integer status) {
        SysRole sysRole = new SysRole()
                .setId(roleId)
                .setStatus(status);
        updateById(sysRole);
    }

    @Override
    public void assignPermissions(RolePermissionDTO permissionDTO) {
        if(Objects.isNull(permissionDTO.getRoleId())){
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);
        }
        List<Integer> menuIds = permissionDTO.getMenuIds().stream().filter(m -> m<10000).collect(Collectors.toList());
        List<Integer> permissionIds = permissionDTO.getMenuIds().stream().filter(m -> m>=10000).collect(Collectors.toList());
        List<SysRolePermission> list = new ArrayList<>(menuIds.size());
        for(Integer permissionId : permissionIds){
            SysRolePermission sysRolePermission = new SysRolePermission()
                    .setRoleId(permissionDTO.getRoleId())
                    .setPermissionId(permissionId);
            list.add(sysRolePermission);
        }
        // 先删除再插入
        sysRolePermissionMapper.delete(new LambdaQueryWrapper<SysRolePermission>()
                .eq(SysRolePermission::getRoleId, permissionDTO.getRoleId())
        );
        sysRolePermissionMapper.insertBatch(list);
        List<SysRoleMenu> roleMenus = new ArrayList<>(permissionIds.size());
        for(Integer menuId : menuIds){
            SysRoleMenu roleMenu = new SysRoleMenu()
                    .setRoleId(permissionDTO.getRoleId())
                    .setMenuId(menuId);
            roleMenus.add(roleMenu);
        }
        // 删除角色菜单关联
        sysRoleMenuService.removeByRoleId(permissionDTO.getRoleId());
        sysRoleMenuService.saveBatch(roleMenus);
    }

    @Override
    @Transactional
    public void deleteRole(Integer id) {
        removeById(id);
        sysRolePermissionMapper.deleteById(id);
    }
}
